import { mergeDeepRight } from "ramda";
import { signal, effect } from "@preact/signals";
import { moveItem } from "./utilities";
import { vendorActions } from "./Vendor";
import { types } from "./Widgets/hitokoto";

const key = "lemon_daisy_settings";
const stor = globalThis.localStorage;

const defaultSettings = {
  theme: 0,
  actions: {
    logoClick: 0,
    logoPress: 1,
    searchClick: 1,
    searchPress: 0,
    suggestPress: 5,
    historyPress: 5,
    favoPress: 10,
    linkPress: 4,
  },
  searchPart: {
    showSuggest: true,
    suggestIcon: true,
    suggestSources: [
      { id: 0, show: true, max: 0 },
      { id: 1, show: true, max: 0 },
      { id: 2, show: true, max: 0 },
      { id: 3, show: true, max: 0 },
    ],
    suggestFrom: 0,
    suggestTimeout: 2000,
    suggestHeightP: 240,
    suggestHeightPK: 80,
    suggestHeightL: 120,
    suggestHeightLK: 0,
    historySorter: 7,
    showPreset: true,
    showEngine: true,
    newTab: true,
    showButtonAtEmpty: true,
    leftButton: 0,
    width: 100,
    radius: 1,
    caseInsensitive: true,
    top: 20,
    logoWidth: 120,
    logoHeight: 64,
    logoRadius: 0.03,
    logoVendor: true,
  },
  favo: {
    newTab: true,
    /* 表格布局 */
    width: 75,
    radius: 1,
    showTitle: true,
    borderStyle: false,
    columnGap: 12,
    rowGap: 12,
    size: 48,
    /* 弹性布局 */
    flexBox: false,
    flexWidth: 75,
    flexAlign: 1,
    flexTheme: 0,
    flexStyle: 0,
    flexRadius: 0.5,
  },
  widget: {
    enabled: false,
    top: 20,
    items: [
      { id: 0, show: true },
      { id: 1, show: true },
      { id: 2, show: true },
      { id: 3, show: true },
    ],
    hitokotoTypes: Object.keys(types),
    hitokotoFrom: true,
    noteRows: 3,
    calendarMonday: false,
    calendarPast: true,
    calendarToday: 0,
    calendarWeekend: 6,
  },
};

export const flexAligns = {
  "flex-start": "左对齐",
  center: "居中",
  "flex-end": "右对齐",
  "space-between": "分散对齐",
  "space-evenly": "环绕",
};

export const settings = signal(structuredClone(defaultSettings));
export const box = document.createElement("body");
export const inner = document.createElement("main");

let autoDarkState = false;

function changing(dark) {
  inner.className = dark ? "dark" : "light";
  inner.dataset.theme = dark ? "night" : "totaldonut";
}

export function changeDark(autoDark) {
  if (settings.value.theme === 1) {
    changing(false);
  } else if (settings.value.theme === 2) {
    changing(true);
  } else if (typeof autoDark == "boolean") {
    changing(autoDark);
    autoDarkState = autoDark;
  }
}

effect(() => {
  const htmlStyle = box.style;
  htmlStyle.setProperty(
    "--search-bar-width",
    `calc(min(80vw, 520px) * ${settings.value.searchPart.width / 100})`,
  );
  htmlStyle.setProperty(
    "--search-bar-radius",
    `${20 * settings.value.searchPart.radius}px`,
  );
  htmlStyle.setProperty(
    "--favo-flex-radius",
    `${16 * settings.value.favo.flexRadius}px`,
  );
  if (settings.value.theme >= 0) changeDark(autoDarkState);
});

export const actions = [
  ...[
    "什么也不做",
    "打开主页设置",
    "清空搜索历史",
    "删除选中历史",
    "复制内容",
    "填入搜索框", // 5
    "作为链接打开",
    "作为链接在新标签打开",
    "清空搜索框",
    "作为关键词搜索",
    "复制标题", // 10
    "标题填入搜索框",
    "复制地址",
    "当前标签打开",
    "新标签打开",
    "打开收藏", // 15
    "打开链接",
    "搜索不记录历史",
    "切换上一个搜索引擎",
    "切换下一个搜索引擎",
  ].map((name, id) => ({ name, id })),
  ...vendorActions,
];

const vendorJumps = vendorActions
  .filter((ao) => ao.type === "jump")
  .map((ao) => ao.id);

const vendorInputs = vendorActions
  .filter((ao) => ao.type === "input")
  .map((ao) => ao.id);

export const events = {
  logoClick: {
    name: "点击 Logo",
    actions: [0, 1, 2, 18, 19, ...vendorJumps],
  },
  logoPress: {
    name: "按住 Logo",
    actions: [0, 1, 2, 18, 19, ...vendorJumps],
  },
  searchPress: {
    name: "按住搜索按钮",
    actions: [0, 1, 2, 6, 7, 8, 17, 18, 19, ...vendorJumps, ...vendorInputs],
  },
  suggestPress: {
    name: "按住搜索内容建议",
    actions: [0, 4, 5, 6, 7, 9, 17, ...vendorInputs],
  },
  historyPress: {
    name: "按住搜索历史建议",
    actions: [0, 3, 4, 5, 6, 7, 9, 17, ...vendorInputs],
  },
  linkPress: {
    name: "按住提取链接建议",
    actions: [0, 4, 5, 6, 7, 9, ...vendorInputs],
  },
  favoPress: { name: "按住搜索收藏建议", actions: [0, 10, 11, 12, 13, 14] },
  searchClick: {
    name: "搜索框内容为空时，点击搜索按钮",
    actions: [0, 1, 2, 18, 19, ...vendorJumps],
  },
};

export function initSettings() {
  if (stor[key]?.startsWith("{")) {
    const data = mergeDeepRight(
      structuredClone(settings.value),
      JSON.parse(stor[key]),
    );
    const availableWidgetsCount = defaultSettings.widget.items.length;
    let currentCount = data.widget.items.length;
    if (currentCount > availableWidgetsCount) {
      const list = structuredClone(data.widget.items);
      data.widget.items = list.filter(
        (item) => item.id < availableWidgetsCount,
      );
      currentCount = availableWidgetsCount;
    }
    while (currentCount < availableWidgetsCount) {
      data.widget.items.push({ id: currentCount, show: true });
      currentCount++;
    }
    settings.value = data;
  }
  stor[key] = JSON.stringify(settings.value);
}

function store(data) {
  stor[key] = JSON.stringify(data);
  settings.value = data;
}

export function changeSetting(path, property, value) {
  const current = structuredClone(settings.value);
  if (path === "") {
    current[property] = value;
  } else {
    current[path][property] = value;
  }
  store(current);
}

export function clearSettings() {
  delete stor[key];
}

export function importSettings(data) {
  store(structuredClone(data));
}

export function resetSettings() {
  importSettings(defaultSettings);
}

export function moveGroup(id, up, area = "widget", property = "items") {
  const current = structuredClone(settings.value);
  const changed = moveItem(current[area][property], id, up, "id");
  current[area][property] = changed;
  store(current);
}

export function setGroup(
  id,
  show,
  area = "widget",
  property = "items",
  attribute = "show",
) {
  const current = structuredClone(settings.value);
  const changed = current[area][property].map((item) =>
    item.id === id ? { ...item, [attribute]: show } : item,
  );
  current[area][property] = changed;
  store(current);
}

export function queryStatus(id, area, property) {
  return settings.value[area][property].find((item) => id === item.id)?.show;
}
